#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <jsoncpp/json/json.h>
#include "Util.hpp"

// #define MYSELF 1      // 有这个宏的时候用自己的序列化方案，没有用别人的

// 给网络版本计算器定制协议
// 都需要进行序列化/反序列化
namespace Protocol_ns
{
    // 分隔符宏
    #define SEP " "
    #define SEP_LEN strlen(SEP)
    // 报头宏
    #define HEADER_SEP "\r\n"
    #define HEADER_SEP_LEN strlen("\r\n")

    // 添加报头 10 + 20 ==> len\r\n10 + 20\r\n
    std::string AddHeader(const std::string& str)
    {
        std::string s = std::to_string(str.size());
        s += HEADER_SEP;
        s += str;
        s += HEADER_SEP;
        return s;
    }

    // 去掉报头提取数据：len\r\n10 + 20\r\n ==> 10 + 20
    std::string RemoveHeader(const std::string& str, int len)
    {
        return str.substr(str.size()-HEADER_SEP_LEN-len, len);
    }

    // 读取字符串并检查是否完整，完整返回报头长度
    int ReadPackage(int sock, std::string& inbuffer, std::string* package)
    {
        std::cout << "ReadPackage inbuffer 之前:" << inbuffer << std::endl;
        // 读取字符串
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer)-1, 0);
        if(s <= 0)
        {
            return -1;
        }
        buffer[s] = 0;
        inbuffer += buffer;

        std::cout << "ReadPackage inbuffer 之中:" << inbuffer << std::endl;
        // 解析检查字符串是否完整
        auto pos = inbuffer.find(HEADER_SEP);
        if(pos == std::string::npos)
        {
            return 0;
        }
        std::string lenStr = inbuffer.substr(0, pos);
        int len = Util::toInt(lenStr);
        int targetpackageLen = lenStr.size() + len + 2*HEADER_SEP_LEN;
        if(inbuffer.size() < targetpackageLen)
        {
            return 0;
        }
        *package = inbuffer.substr(0, targetpackageLen);
        inbuffer.erase(0, targetpackageLen);
        std::cout << "ReadPackage inbuffer 之后:" << inbuffer << std::endl;
        return len;
    }



    class Request
    {
    public:
        Request()
        {
        }
        Request(int x, int y, char op)
            : _x(x), _y(y), _op(op)
        {
        }

        // 序列化:struct -> string
        bool Serialize(std::string *outStr)
        {
            *outStr = "";

#ifdef MYSELF
            std::string x_string = std::to_string(_x);
            std::string y_string = std::to_string(_y);

            // 序列化
            *outStr = x_string + SEP + _op + SEP + y_string;
#else
            Json::Value root;   // Value是万能对象，通过重载[]可以接收任意的kv类型
            root["x"] = _x;     // 传入的v值会自动转成字符串
            root["y"] = _y;
            root["op"] = _op;

            Json::FastWriter writer;    // 序列化，将字符串变为一行的
            // Json::StyledWriter writer      // 序列化，将字符串变为风格化，比较好看
            *outStr = writer.write(root);

#endif
            return true;
        }

        // 反序列化:string -> struct
        bool Deserialize(const std::string &inStr)
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if(result.size() != 3)
            {
                return false;
            }
            if(result[1].size() != 1)
            {
                return false;
            }
            _x = Util::toInt(result[0]);
            _y = Util::toInt(result[2]);
            _op = result[1][0];
#else
            Json::Value root;
            Json::Reader reader;    // Reader是用来进行反序列化的
            reader.parse(inStr, root); // 将inStr序列化数据读取到root中
            _x = root["x"].asInt();    // 通过k找到v然后将字符串转化成int类型
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
            return true;
        }

        ~Request()
        {
        }

    public:
        int _x;
        int _y;
        char _op;
    };




    class Response
    {
    public:
        Response()
        {
        }
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }
        // 序列化
        bool Serialize(std::string *outStr)
        {
            *outStr = "";
#ifdef MYSELF
            std::string result_string = std::to_string(_result);
            std::string code_string = std::to_string(_code);

            *outStr = result_string + SEP + code_string;
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            Json::FastWriter writer;
            *outStr = writer.write(root);
#endif
            return true;

        }
        // 反序列化
        bool Deserialize(const std::string& inStr)
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(inStr, SEP, &result);
            if(result.size() != 2)
            {
                return false;
            }
            _result = Util::toInt(result[0]);
            _code = Util::toInt(result[1]);
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(inStr, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();
#endif
            return true;
        }
        ~Response()
        {
        }

    public:
        int _result;
        int _code;
    };
}
